package com.group.common.utils;

import javafx.application.Platform;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;

import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * 用于JavaFX开发的工具类
 *
 * @author 刘海翔
 * @version 3.0
 * @since 1.0
 */
public class MyUtils {

    /**
     * 根据文件名给出的路径读取文件内容
     *
     * @param pathRoot    文件路径，从根文件夹开始寻找
     * @param <T> 泛型
     * @return 文件内容，如果文件为空或不存在则返回 null
     */
    public static <T> HashMap<String, T> readFileToHashMap(String pathRoot) {
        try {
            File file = new File(pathRoot);
            if (!file.exists()) {
                throw new FileNotFoundException();
            }
            HashMap<String, T> userHashMap = new HashMap<>();
            if (file.length() > 0) {
                try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) {
                    HashMap<String, T> existingUsers = (HashMap<String, T>) ois.readObject();
                    if (existingUsers != null) {
                        userHashMap = existingUsers;
                    }
                }
            }
            return userHashMap;
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 根据文件名给出的路径读取文件内容
     *
     * @param pathRoot 文件路径，从根文件夹开始寻找
     * @param <T> 泛型
     * @return 文件内容，如果文件为空或不存在则返回 null
     */
    public static <T> ArrayList<T> readFileToArrayList(String pathRoot) {
        try {
            File file = new File(pathRoot);
            if (!file.exists()) {
                throw new FileNotFoundException();
            }
            ArrayList<T> userArrayList = new ArrayList<>();
            if (file.length() > 0) {
                try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) {
                    ArrayList<T> existingUsers = (ArrayList<T>) ois.readObject();
                    if (existingUsers != null) {
                        userArrayList = existingUsers;
                    }
                }
            }
            return userArrayList;
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 从指定路径读取文件内容，并反序列化为指定的泛型类型对象
     * 需要搭配try-catch块使用
     *
     * @param pathRoot 文件路径，从根文件夹开始寻找
     * @param clazz    目标类的 Class 对象，用于类型检查和转换
     * @param <T>      泛型类型
     * @return 反序列化后的对象，若文件为空或不存在则返回 null
     * @throws IOException            如果读取文件时发生 I/O 错误
     * @throws ClassNotFoundException 如果找不到对应的类
     */
    public static <T> T readFile(String pathRoot, Class<T> clazz) throws IOException, ClassNotFoundException {
        File file = new File(pathRoot);
        if (!file.exists()) {
            throw new FileNotFoundException("文件不存在: " + pathRoot);
        }

        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) {
            Object obj = ois.readObject();
            if (clazz.isInstance(obj)) {
                return clazz.cast(obj);
            } else {
                throw new ClassCastException("文件内容不是期望的类型: " + clazz.getName());
            }
        }
    }


    /**
     * 根据文件名给出的路径写入文件内容
     *
     * @param pathRoot    文件路径，从根文件夹开始寻找
     * @param userHashMap 文件内容
     * @param <T>         泛型
     */
    public static <T> void writeHashMapToFile(String pathRoot, HashMap<String, T> userHashMap) {
        try {
            File file = new File(pathRoot);
            if (!file.exists()) {
                file.createNewFile();
            }
            try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file))) {
                oos.writeObject(userHashMap);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 根据文件名给出的路径写入文件内容
     * @param pathRoot 文件路径，从根文件夹开始寻找
     * @param userArrayList 文件内容
     * @param <T> 泛型
     */
    public static <T> void writeArrayListToFile(String pathRoot, ArrayList<T> userArrayList) {
        try {
            File file = new File(pathRoot);
            if (!file.exists()) {
                file.createNewFile();
            }
            try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file))) {
                oos.writeObject(userArrayList);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 将对象写入指定路径的文件中，支持任意可序列化对象
     * 需要搭配try-catch块使用
     *
     * @param pathRoot 文件路径，从根文件夹开始寻找
     * @param object   要写入的对象（必须实现 Serializable）
     * @throws IOException 如果写入文件失败
     */
    public static void writeFile(String pathRoot, Serializable object) throws IOException {
        File file = new File(pathRoot);
        if (!file.exists()) {
            file.createNewFile();
        }
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file))) {
            oos.writeObject(object);
        }
    }

    /**
     * 显示一个提示框
     *
     * @param title         提示框的标题
     * @param headerText    提示框的头部
     * @param contentText   提示框的内容
     * @param alertType     提示框的类型
     */
    public static void showAlert(String title, String headerText, String contentText, Alert.AlertType alertType) {
        Alert alert = new Alert(alertType);
        alert.setTitle(title);
        alert.setHeaderText(headerText);
        alert.setContentText(contentText);
        alert.showAndWait();
    }

    /**
     * 显示一个视图
     *
     * @param stage 显示的stage
     * @param pathName MyUtils类到文件所在在文件夹的相对路径，末尾需要加"/"
     * @param fileName 文件名
     */
    public static void showView(Stage stage, String pathName, String fileName) {
        try {
            String pathRoot = pathName + fileName;
            FXMLLoader fxmlLoader = new FXMLLoader();
            URL url = MyUtils.class.getResource(pathRoot);
            fxmlLoader.setLocation(url);
            Parent root = fxmlLoader.load();
            Object controller = fxmlLoader.getController();
            if (controller instanceof javafx.fxml.Initializable) {
                ((javafx.fxml.Initializable) controller).initialize(null, null);
            } else {
                java.lang.reflect.Method method = controller.getClass().getMethod("initialize");
                method.invoke(controller);
            }
            Scene scene = new Scene(root);
            stage.setScene(scene);
            stage.show();
        } catch (IOException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    /**
     * 显示一个视图
     *
     * @param stage         显示的stage
     * @param depth         MyUtils类到源的深度
     * @param rootPath      文件来自源根的路径
     */
    public static void showView(Stage stage, int depth, String rootPath) {
        String path = "";
        for (int i = 0; i < depth; i++) {
            path = path + "../";
        }
        rootPath = path + rootPath;
        showView(stage, "", rootPath);
    }

    /**
     * 显示一个视图，仅适用于tMyUtils类到源的深度为3的情况
     *
     * @param stage       显示的stage
     * @param rootPath    文件来自源根的路径文件来自源根的路径
     */
    public static void showView(Stage stage, String rootPath) {
        showView(stage, 3, rootPath);
    }

    /**
     * 将数据列表绑定到 TableView，并自动设置指定字段的显示
     *
     * @param tableView       要绑定数据的 TableView
     * @param items           数据源集合
     * @param columnMapping   TableColumn 到对象属性名的映射
     * @param <T>             数据项类型
     */
    public static <T> void showTableView(TableView<T> tableView, List<T> items, Map<TableColumn<T, ?>, String> columnMapping) {
        if (tableView == null || items == null || columnMapping == null) {
            throw new IllegalArgumentException("参数 tableView、items 和 columnMapping 不得为 null");
        }
        for (Map.Entry<TableColumn<T, ?>, String> entry : columnMapping.entrySet()) {
            TableColumn<T, ?> column = entry.getKey();
            String propertyName = entry.getValue();
            column.setCellValueFactory(new PropertyValueFactory<>(propertyName));
        }
        Platform.runLater(() -> {                   //确保运行在JavaFX线程，直接用addAll方法会报错
            tableView.getItems().setAll(items);
        });
    }

    /**
     * 点击按钮后跳转到指定的FXML页面
     *
     * @param event        事件
     * @param rootPath     目标FXML文件路径（相对于资源根目录）
     */
    public static void navigateToView(ActionEvent event, String rootPath) {
        Stage currentStage = (Stage) ((Node) event.getSource()).getScene().getWindow();
        showView(currentStage, rootPath);
    }

}
